<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if (! class_exists('PrunusVirtualTable')) {
  /**
   * PrunusVirtualTable
   * 
   * Virtual Prunus Table interface
   * 
   * @package Prunus   
   * @author agosto <agosto@7dedos.com>
   * @copyright	Copyright (c) 2009-2010, 7dedos
   * @link http://www.7dedos.com
   * @version 0.1
   * @access public
   */
  abstract class PrunusVirtualTable extends Model {
    protected $tableName;
    protected $tablePrefix;
    protected $listColumns;
    protected $getColumns;
    protected $relaciones;
    protected $dataArray;
    protected $ci;
    const IdColumn = "id";
    const SafeUrlColumn = "safe_url";
    const AliveColumn = "alive";
    const Separator = "_";
    
    /**
     * PrunusVirtualTable::__construct()
     * 
     * @param string $tableName Name of the thable
     * @param string $tablePrefix Prefix for every column on the table, including the trailing _
     * @param array $listColumns  Array of strings with columns' names for listing
     * @param array $getColumns  Array of strings with columns' names for getRecord
     * @return
     */
    public function __construct($tableName, $tablePrefix, $listColumns, $getColumns, $dataArray) {
      parent::__construct();
      $this->ci =& get_instance();
      $this->tableName = $tableName;
      $this->tablePrefix = $tablePrefix;
      $this->listColumns = $listColumns;
      $this->getColumns = $getColumns;
      $this->relaciones = array();
      $this->dataArray = $dataArray;
    }
    
    public function getTableName()    { return ($this->tableName); }
    public function getTablePrefix()  { return ($this->tablePrefix); }
    public function getIdColumn()      { return ($this->tablePrefix . PrunusVirtualTable::Separator . PrunusVirtualTable::IdColumn); }
    public function getAliveColumn()   { return ($this->tablePrefix . PrunusVirtualTable::Separator . PrunusVirtualTable::AliveColumn); }
    public function getSafeUrlColumn() { return ($this->tablePrefix . PrunusVirtualTable::Separator . PrunusVirtualTable::SafeUrlColumn); }

    
    public function getRelaciones() {
      return ($this->relaciones);
    }
    public function getRelacion($name) {
      return ($this->relaciones[$name]);
    }

    public function addRelation(&$relation) {
      $this->relaciones[$relation->getName()] = $relation;
    }
    
    /**
     * PrunusVirtualTable::countRecords()
     * 
     * @param integer|null $alive indicates if alive/non-alive records are counted. (null means don't filter by this value)
     * @param array|null $filters it uses array's key for column name and array's value for the value used on where  
     * @param array|null $filters as string it's the whole where clause (literal). as an array it uses array's key for column name and array's value for the value used on where  
     * @return integer records matching the parameters
     */
    public function countRecords($alive = 1, $filters = null, $inlist = null) {
      $result = $this->_listRecords( TRUE, $alive, $filters, $inlist );
      return (count($result));
    }
    
    /**
     * PrunusVirtualTable::listRecords()
     * 
     * @param integer $alive optional integer indicating if alive/non-alive records are counted. (null means don't filter by this value)
     * @param array|null $filters it uses array's key for column name and array's value for the value used on where  
     * @param array|null $inlist array where every record name is the column name, and the value is an array of values to test
     * @param integer|null $offset starting record on paged query. to avoid paging, use null on this column
     * @param integer|null $limit if $offset is not null, this value contains the number of rows per page 
     * @return CI_DB A class containing the get method results
     */
    public function listRecords($alive = 1, $filters = null, $inlist = null, $offset = null, $limit = null) {
      return $this->_listRecords( FALSE, $alive, $filters, $inlist, $offset, $limit );
    }
    
    /**
     * PrunusVirtualTable::_listRecords()
     * 
     * @param bool $count TRUE means the result of the query is the number of rows, otherwhise it returns the rows 
     * @param integer $alive optional integer indicating if alive/non-alive records are counted. (null means don't filter by this value)
     * @param array|null $filters it uses array's key for column name and array's value for the value used on where  
     * @param array|null $inlist array where every record name is the column name, and the value is an array of values to test
     * @param integer|null $offset starting record on paged query. to avoid paging, use null on this column
     * @param integer|null $limit if $offset is not null, this value contains the number of rows per page 
     * @return CI_DB A class containing the get method results
     */
    private function _listRecords($count, $alive, $filters, $inlist, $offset = null, $limit = null) {
      $resultArray = array();
      $rowNum = 0;
      
      foreach ($this->dataArray as $row) {
        $rowNum++;
        $rowOk = TRUE;
        
        //filtros
        foreach ($row as $columnName=>$columnValue) {
          if ($rowOk) if ($alive !== null) if ($columnName == $this->tablePrefix . '_' . PrunusVirtualTable::AliveColumn) if ($columnValue !== $alive) $rowOk = FALSE;
          if ($rowOk) if ($inlist !== null)  foreach ($inlist as $column=>$list)   if ($column == $columnName) if (! in_array($columnValue,$list)) $rowOk = FALSE;
          if ($rowOk) if ($filters !== null) foreach ($filters as $column=>$value) if ($column == $columnName) if ($columnValue !== $value) $rowOk = FALSE;
        }
        
        if ($rowOk) {
          $newRow = array();
          
          foreach ($row as $columnName=>$columnValue) {
            if (in_array($columnName,$this->listColumns)) {
              $newRow[$columnName] = $columnValue;
            }
          }
          
          if ( ! $count ) {
            if ($offset !== null) {
              if ($rowNum >= $offset) {
                if ($rowNum <= $offset + $limit) {
                  $resultArray[] = $newRow;
                }
              }
            } else {
              $resultArray[] = $newRow;
            }
          } else {
            $resultArray[] = $newRow;
          }
        }
      }
      
      return ($resultArray);
    }

    /**
     * PrunusVirtualTable::getRecord()
     * 
     * @param integer|string $id if integer it's the column's id. if string, it's column's safe url.
     * @return CI_DB A class containing the get method results
     */
    public function getRecord($id) {
      $result = array();
      if (is_numeric($id)) {
        $targetColumnName = $this->tablePrefix . '_' . PrunusVirtualTable::IdColumn;
      } else {
        $targetColumnName = $this->tablePrefix . '_' . PrunusVirtualTable::SafeUrlColumn;
      }
      foreach ($this->dataArray as $row) if ($row[$targetColumnName] == $id) $result = $row;
      return ( $result );
    }
  
  
  }
}
